package service

import (
	"context"
	"fmt"
	jwt "github.com/gogf/gf-jwt/v2"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/text/gstr"
	"miaoyuadmin/api/backend/response"
	"miaoyuadmin/internal/model"
	"strings"
	"time"
)

var authService *jwt.GfJWTMiddleware

func Auth() *jwt.GfJWTMiddleware {
	return authService
}

func init() {
	auth := jwt.New(&jwt.GfJWTMiddleware{
		Realm:           "miaoyu admin",
		Key:             []byte("miaoyu admin key"),
		Timeout:         time.Minute * 30,
		MaxRefresh:      time.Hour * 24,
		IdentityKey:     "id",
		TokenLookup:     "header:Authorization,query:token,cookie:jwt",
		TokenHeadName:   "mytoken",
		TimeFunc:        time.Now,
		Authenticator:   Authenticator,
		Unauthorized:    Unauthorized,
		PayloadFunc:     PayLoadFunc,
		IdentityHandler: IdentityHandler,
	})
	authService = auth
}

//PayLoadFunc 登录期间的设置私有载荷的函数，默认设置authenticator函数回调的所有内容
func PayLoadFunc(data interface{}) jwt.MapClaims {
	claims := jwt.MapClaims{}
	params := data.(map[string]interface{})
	if len(params) > 0 {
		for k, v := range params {
			claims[k] = v
		}
	}
	return claims
}

//IdentityHandler 解析并设置用户身份信息，并设置身份信息至每次请求中
func IdentityHandler(ctx context.Context) interface{} {
	claims := jwt.ExtractClaims(ctx)
	return claims[authService.IdentityKey]
}

//Unauthorized 处理不进行授权的逻辑
func Unauthorized(ctx context.Context, code int, message string) {
	r := g.RequestFromCtx(ctx)
	curPath := r.Request.URL.Path
	unAuthVar, _ := g.Cfg().Get(ctx, "unauthlist")
	unAuthStr := unAuthVar.String()
	unAuthList := strings.Split(unAuthStr, ",")
	if gstr.InArray(unAuthList, curPath) {
		r.Middleware.Next()
	} else {
		response.UniResp(r, "请在登录后继续操作！", "/login.mhtml")
	}

}

//Authenticator 用户标识 map 私有属性，根据登录信息对用户进行身份验证的回调函数
func Authenticator(ctx context.Context) (interface{}, error) {

	var (
		r  = g.RequestFromCtx(ctx)
		in model.UserLoginInput
	)
	if err := r.Parse(&in); err != nil {
		return "", err
	}

	user, err := Login().CheckUserPassword(ctx, in)
	if err != nil {
		return nil, jwt.ErrFailedAuthentication
	}
	fmt.Println("auth", user)
	payloadMap := make(map[string]interface{})
	payloadMap["id"] = user.Id
	payloadMap["username"] = user.UserName

	return payloadMap, err

}
